home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 25 / CU Amiga Magazine's Super CD-ROM 25 (1998)(EMAP Images)(GB)(Track 1 of 2)[!][issue 1998-08].iso / CUCD / Programming / QuakeTools / src / libqdisplay / poly.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-12  |  11.2 KB  |  343 lines

  1. #define    LIBQDISPLAY_CORE
  2. #include "../include/libqdisplay.h"
  3.  
  4. /*
  5.  *   Render a Quake polygon:
  6.  *      read it from the db
  7.  *      transform it into 3d
  8.  *      clip it in 3d
  9.  *      compute the 2d texture gradients
  10.  *      scan convert
  11.  *      pass off the spans
  12.  */
  13.  
  14. static point_3d defaultPoints[32], *defaultVList[32];
  15. static fix scan[768][2];
  16. static struct texture **cachedFaces;
  17.  
  18. void setup_default_point_list(void)
  19. {
  20.   int i;
  21.  
  22.   for (i = 32 - 1; i >= 0; --i)
  23.     defaultVList[i] = &defaultPoints[i];
  24. }
  25.  
  26. void InitFaceCache(__memBase) {
  27.   if(!(cachedFaces = (struct texture **)kmalloc(bspMem->numfaces * sizeof(struct texture *))))
  28.     Error("failed to allocate face-cache\n");
  29. }
  30.  
  31. static void scan_convert(point_3d * a, point_3d * b)
  32. {
  33.   void *temp;
  34.   int right;
  35.   fix x, dx;
  36.   int y, ey;
  37.  
  38.   if (a->sy == b->sy)
  39.     return;
  40.     
  41.   if (a->sy < b->sy)
  42.     right = 0;
  43.   else {
  44.     temp = a;
  45.     a = b;
  46.     b = temp;
  47.     right = 1;
  48.   }
  49.  
  50.   // compute dxdy
  51.   dx = FLOAT_TO_INT(scalw((b->sx - a->sx), 16) / (b->sy - a->sy));    // * 65536.0
  52.   x = a->sx;
  53.   y = FIX_INT(a->sy);
  54.   ey = FIX_INT(b->sy);
  55.   x += FLOAT_TO_INT(((double)dx * ((y << 16) - a->sy)) * (1 / 65534.0));
  56.  
  57.   while (y < ey) {
  58.     scan[y][right] = x;
  59.     x += dx;
  60.     ++y;
  61.   }
  62. }
  63.  
  64. static void draw_poly(int n, point_3d ** vl)
  65. {
  66.   int i, j, y, ey;
  67.   fix ymin, ymax;
  68.  
  69.   // find max and min y height
  70.   ymin = ymax = vl[0]->sy;
  71.   for (i = 1; i < n; ++i) {
  72.     if (vl[i]->sy < ymin)
  73.       ymin = vl[i]->sy;
  74.     else if (vl[i]->sy > ymax)
  75.       ymax = vl[i]->sy;
  76.   }
  77.  
  78.   // scan out each edge
  79.   j = n - 1;
  80.   for (i = 0; i < n; ++i) {
  81.     scan_convert(vl[i], vl[j]);
  82.     j = i;
  83.   }
  84.  
  85.   y = FIX_INT(ymin);
  86.   ey = FIX_INT(ymax);
  87.  
  88.   // iterate over all spans and draw
  89.   while (y < ey) {
  90.     int sx = FIX_INT(scan[y][0]), ex = FIX_INT(scan[y][1]);
  91.  
  92.     if (sx < ex)
  93.       draw_span((int)y, (int)sx, (int)ex);
  94.     ++y;
  95.   }
  96. }
  97.  
  98. static void GetMipMaps(__memBase, struct texture *Text, int TMipMap) {
  99.   struct dmiptexlump_t *mtl = (struct dmiptexlump_t *) bspMem->dtexdata;
  100.   struct mipmap *mip = (struct mipmap *) (bspMem->dtexdata + mtl->dataofs[TMipMap]);
  101.   short int i;
  102.  
  103.   if (mip->name[0] == WARP_MIPMAP) {
  104.     switch(mip->name[1]) {
  105.       case 'w': Text->textureType = WATER_TYPE; break;            // *w(ater)...
  106.       case 's': Text->textureType = SLIME_TYPE; break;            // *s(lime)...
  107.       case 'l': Text->textureType = LAVA_TYPE; break;            // *l(ava)...
  108.       case 't': Text->textureType = TELEPORT_TYPE; break;        // *t(eleport)...
  109.       default:  Text->textureType = OTHER_TYPE; break;            // *...
  110.     }
  111.     Text->mipMaps[MIPMAP_0].rawBody.width = WARP_X;
  112.     Text->mipMaps[MIPMAP_0].rawBody.height = WARP_Y;
  113.     Text->mipMaps[MIPMAP_0].rawBody.size = WARP_X * WARP_Y;
  114.     Text->mipMaps[MIPMAP_0].newBody.width = WARP_X;
  115.     Text->mipMaps[MIPMAP_0].newBody.height = WARP_Y;
  116.     Text->mipMaps[MIPMAP_0].newBody.size = WARP_X * WARP_Y;
  117.     Text->textGradient.u = 0;
  118.     Text->textGradient.v = 0;
  119.   }
  120.   else if (!strncmp(mip->name, SKY_MIPMAP, 3)) {
  121.     Text->textureType = SKY_TYPE;
  122.     Text->mipMaps[MIPMAP_0].rawBody.width = SKY_X;
  123.     Text->mipMaps[MIPMAP_0].rawBody.height = SKY_Y;
  124.     Text->mipMaps[MIPMAP_0].rawBody.size = SKY_X * SKY_Y;
  125.     Text->mipMaps[MIPMAP_0].newBody.width = SKY_X;
  126.     Text->mipMaps[MIPMAP_0].newBody.height = SKY_Y;
  127.     Text->mipMaps[MIPMAP_0].newBody.size = SKY_X * SKY_Y;
  128.     Text->textGradient.u = 0;
  129.     Text->textGradient.v = 0;
  130.   }
  131.   else {
  132.     if(mip->name[0] == ANIM_MIPMAP)
  133.       Text->textureType = ANIM_TYPE;
  134.     else
  135.       Text->textureType = WALL_TYPE;
  136.  
  137.     Text->mipMaps[MIPMAP_0].rawBody.width = LittleLong(mip->width);
  138.     Text->mipMaps[MIPMAP_0].rawBody.height = LittleLong(mip->height);
  139.     Text->mipMaps[MIPMAP_0].rawBody.size = Text->mipMaps[MIPMAP_0].rawBody.width * Text->mipMaps[MIPMAP_0].rawBody.height;
  140.     Text->mipMaps[MIPMAP_0].newBody.width = Text->faceExtent.u10;
  141.     Text->mipMaps[MIPMAP_0].newBody.height = Text->faceExtent.v10;
  142.     Text->mipMaps[MIPMAP_0].newBody.size = Text->mipMaps[MIPMAP_0].newBody.width * Text->mipMaps[MIPMAP_0].newBody.height;
  143.     Text->textGradient.u = Text->faceExtent.u0;
  144.     Text->textGradient.v = Text->faceExtent.v0;
  145.   }
  146.   Text->mipMaps[MIPMAP_0].rawBody.data = (unsigned char *)mip + LittleLong(mip->offsets[MIPMAP_0]);
  147.   Text->mipMaps[MIPMAP_0].step = 16;
  148.   Text->mipMaps[MIPMAP_0].shift = 4;
  149.   Text->mipMaps[MIPMAP_0].row = Text->mipMaps[MIPMAP_0].newBody.width - Text->mipMaps[MIPMAP_0].step;
  150.   if((Text->mipMaps[MIPMAP_0].y = Text->faceExtent.v0 % Text->mipMaps[MIPMAP_0].rawBody.height) < 0)
  151.     Text->mipMaps[MIPMAP_0].y += Text->mipMaps[MIPMAP_0].rawBody.height;
  152.   if((Text->mipMaps[MIPMAP_0].x0 = Text->faceExtent.u0 % Text->mipMaps[MIPMAP_0].rawBody.width) < 0)
  153.     Text->mipMaps[MIPMAP_0].x0 += Text->mipMaps[MIPMAP_0].rawBody.width;
  154.   Text->mipMaps[MIPMAP_0].rescale = scalw((double)(8), -3);        // / 8.0;
  155.   
  156.   for(i = MIPMAP_1; i < MIPMAP_MAX; i++) {                // an enum cycles, produces no overflow
  157.     Text->mipMaps[i].rawBody.data = (unsigned char *)mip + LittleLong(mip->offsets[i]);
  158.     Text->mipMaps[i].rawBody.width = Text->mipMaps[MIPMAP_0].rawBody.width >> i;
  159.     Text->mipMaps[i].rawBody.height = Text->mipMaps[MIPMAP_0].rawBody.height >> i;
  160.     Text->mipMaps[i].rawBody.size = Text->mipMaps[MIPMAP_0].rawBody.size >> i >> i;
  161.     Text->mipMaps[i].newBody.width = Text->mipMaps[MIPMAP_0].newBody.width >> i;
  162.     Text->mipMaps[i].newBody.height = Text->mipMaps[MIPMAP_0].newBody.height >> i;
  163.     Text->mipMaps[i].newBody.size = Text->mipMaps[MIPMAP_0].newBody.size >> i >> i;
  164.     Text->mipMaps[i].step = 16 >> i;
  165.     Text->mipMaps[i].shift = 4 - i;
  166.     Text->mipMaps[i].row = Text->mipMaps[i].newBody.width - Text->mipMaps[i].step;
  167.     Text->mipMaps[i].rescale = scalw(Text->mipMaps[MIPMAP_0].rescale, -i);
  168.     Text->mipMaps[i].y = Text->mipMaps[MIPMAP_0].y >> i;
  169.     Text->mipMaps[i].x0 = Text->mipMaps[MIPMAP_0].x0 >> i;
  170.   }
  171.   
  172.   if(!(Text->tiled = (unsigned char *)kmalloc((Text->mipMaps[MIPMAP_0].newBody.size + 1) * sizeof(unsigned char))))
  173.     Error("failed to allocate mipmap-body\n");
  174.   Text->texChanged = TRUE;                        // be very safe
  175. }
  176.  
  177. static void GetExtents(__memBase, int face, struct texture *Text, int TInfo) {
  178.   float uv[32][2], *u, *v, umin, umax, vmin, vmax;
  179.   short int i, n = bspMem->dfaces[face].numedges;
  180.   int *se = &bspMem->dsurfedges[bspMem->dfaces[face].firstedge + n];
  181.  
  182.   u = bspMem->texinfo[TInfo].vecs[0];
  183.   v = bspMem->texinfo[TInfo].vecs[1];
  184.  
  185.   for (i = n - 1; i >= 0; --i) {
  186.     int j = *--se;
  187.     float *loc;
  188.  
  189.     if (j < 0)
  190.       loc = bspMem->dvertexes[bspMem->dedges[-j].v[1]].point;
  191.     else
  192.       loc = bspMem->dvertexes[bspMem->dedges[j].v[0]].point;
  193.  
  194.     uv[i][0] = DotProduct(loc, u) + u[3];
  195.     uv[i][1] = DotProduct(loc, v) + v[3];
  196.   }
  197.   umin = umax = uv[0][0];
  198.   vmin = vmax = uv[0][1];
  199.   for (i = n - 1; i >= 0; --i) {
  200.     if (uv[i][0] < umin)
  201.       umin = uv[i][0];
  202.     else if (uv[i][0] > umax)
  203.       umax = uv[i][0];
  204.     if (uv[i][1] < vmin)
  205.       vmin = uv[i][1];
  206.     else if (uv[i][1] > vmax)
  207.       vmax = uv[i][1];
  208.   }
  209.   
  210.   Text->faceExtent.u0 = (int)(umin) & ~15;
  211.   Text->faceExtent.v0 = (int)(vmin) & ~15;
  212.   Text->faceExtent.u1 = (int)(ceil(scalw(umax, -4))) << 4;        // / 16
  213.   Text->faceExtent.v1 = (int)(ceil(scalw(vmax, -4))) << 4;        // / 16
  214.   Text->faceExtent.u10 = Text->faceExtent.u1 - Text->faceExtent.u0;
  215.   Text->faceExtent.v10 = Text->faceExtent.v1 - Text->faceExtent.v0;
  216.   
  217.   if(bspMem->dfaces[face].lightofs != -1) {
  218.     Text->lightdata = &bspMem->dlightdata[bspMem->dfaces[face].lightofs];
  219.  
  220.     Text->lightmap.width = ((Text->faceExtent.u10) >> 4) + 1;
  221.     Text->lightmap.height = ((Text->faceExtent.v10) >> 4) + 1;
  222.     Text->lightmap.size = Text->lightmap.width * Text->lightmap.height;
  223.     if(!(Text->lightmap.data = (unsigned char *)kmalloc((Text->lightmap.size + 1) * sizeof(int))))
  224.       Error("failed to allocate lightmap for face\n");
  225.  
  226.     for(i = 0; i < MAXLIGHTMAPS; i++) {
  227.       short int lightStyle;
  228.       
  229.       lightStyle = (short int)bspMem->dfaces[face].styles[i];
  230.       
  231.       if(lightStyle == 255)
  232.         break;
  233.       if(lightStyle > 11)
  234.         lightStyle = 0;
  235.       
  236.       Text->lightSString[i] = &lightstyleStrings[lightStyle][0];
  237.       Text->lightSLength[i] = lightstyleLengths[lightStyle];
  238.     }
  239.   }
  240.   else
  241.     Text->lightdata = 0;
  242.  
  243.   Text->texChanged = TRUE;                        // be very safe
  244. }
  245.  
  246. static void GetGradients(__memBase, int face, struct texture *Text, int TInfo) {
  247.   struct dplane_t *plane = Text->textGradient.plane = &bspMem->dplanes[bspMem->dfaces[face].planenum];
  248.   float dot, dot0, dot1;
  249.   vec3_t norm;
  250.   float *vec0 = bspMem->texinfo[TInfo].vecs[0];
  251.   float *vec1 = bspMem->texinfo[TInfo].vecs[1];
  252.   
  253.   CrossProduct(vec0, vec1, norm);
  254.   
  255.   dot = DotProduct(norm, plane->normal);
  256.   
  257.   if((dot0 = -DotProduct(vec0, plane->normal) / dot) != 0)        // for setup_uv_vector
  258.     VectorMA(vec0, dot0, norm, Text->textGradient.uv0);
  259.   else
  260.     VectorCopy(vec0, Text->textGradient.uv0);
  261.     
  262.   if((dot1 = -DotProduct(vec1, plane->normal) / dot) != 0)        // for setup_uv_vector
  263.     VectorMA(vec1, dot1, norm, Text->textGradient.uv1);
  264.   else
  265.     VectorCopy(vec1, Text->textGradient.uv1);
  266.  
  267.   VectorScale(norm, (plane->dist / dot), Text->textGradient.scaled);    // for setup_origin_vector;
  268.  
  269.   Text->textGradient.u -= vec0[3];
  270.   Text->textGradient.v -= vec1[3];
  271.   Text->texChanged = TRUE;                        // be very safe
  272. }
  273.  
  274. static struct texture *cache_face(__memBase, int face) {
  275.   struct texture *Text;
  276.   int TInfo = bspMem->dfaces[face].texinfo;
  277.   int TMipMap = bspMem->texinfo[TInfo].miptex;
  278.  
  279.   if(!(Text = (struct texture *)kmalloc(sizeof(struct texture))))
  280.     Error("failed to allocate texture-cache\n");
  281.   
  282.   GetExtents(bspMem, face, Text, TInfo);
  283.   GetMipMaps(bspMem, Text, TMipMap);
  284.   GetGradients(bspMem, face, Text, TInfo);
  285.   Text->texChanged = TRUE;                        // be very safe
  286.   
  287.   return Text;
  288. }
  289.  
  290. void draw_face(__memBase, int face)
  291. {
  292.   int n = bspMem->dfaces[face].numedges;
  293.   int se = bspMem->dfaces[face].firstedge;
  294.   int i, edge, codes_or = 0, codes_and = 0xff;
  295.   point_3d **vlist;
  296.  
  297.   for (i = 0; i < n; ++i) {
  298.     edge = bspMem->dsurfedges[se + i];
  299.     
  300.     if (edge < 0)
  301.       transform_point(&defaultPoints[i], &bspMem->dvertexes[bspMem->dedges[-edge].v[1]].point);
  302.     else
  303.       transform_point(&defaultPoints[i], &bspMem->dvertexes[bspMem->dedges[edge].v[0]].point);
  304.     
  305.     codes_or |= defaultPoints[i].ccodes;
  306.     codes_and &= defaultPoints[i].ccodes;
  307.   }
  308.  
  309.   if (codes_and)
  310.     return;
  311.   if (codes_or)                                    // poly crosses frustrum, so clip it
  312.     n = clip_poly(n, defaultVList, codes_or, &vlist);
  313.   else
  314.     vlist = defaultVList;
  315.  
  316.   /*
  317.    * with this texChange-technique it is possible for example
  318.    * to let light render the bsp-tree, then light marks the
  319.    * last processed face as changed and render the tree again
  320.    * and voila, everything is unchanged but the new lightface
  321.    */
  322.   if (n) {
  323.     struct texture *Text;
  324.  
  325.     if(!(Text = cachedFaces[face]))
  326.       Text = cachedFaces[face] = cache_face(bspMem, face);
  327.  
  328.     if((textureMip = compute_mip_level(bspMem, face)) != Text->lastMip)    // if the mipmap changes, the tex and it lights changes too
  329.       Text->texChanged = TRUE;
  330.  
  331.     GetTMap(bspMem, Text, textureMip);                    // GetTMap must have the capability to set texChange
  332.     compute_texture_gradients(bspMem, Text, textureMip);
  333.     draw_poly(n, vlist);
  334.  
  335.     Text->lastMip = textureMip;                        // set last mip here, perhaps GetTMap should use the old value
  336.     
  337.     /*
  338.      * should we free the whole face if it is an ANIM_MIPMAP?
  339.      * perhaps the sizes etc. changes ...
  340.      */
  341.   }
  342. }
  343.